﻿namespace HuwmanCode.UserAccountControl

open System
open System.Diagnostics
open System.Runtime.InteropServices
open HuwmanCode
open HuwmanCode.Diagnostics.Logging
open HuwmanCode.Runtime.InteropServices

type public ProcessElevation =
    | Unsupported = 0 //Only supported on Vista and above
    | Default = 1     //UAC is probably turned off
    | Elevated = 2    //The process is elevated
    | Limited = 3     //The process is unelevated

type public Uac =
    /// <summary>
    /// The UAC (User Account Control) process elevation
    /// </summary
    static member ProcessElevation
        with get() =
            let getTokenHandle () =
                let procHandle = Process.GetCurrentProcess().Handle
                let mutable tokenHandle:ProcessTokenHandle = Unchecked.defaultof<_>
                OpenProcessToken(procHandle, TokenDesiredAccess.Query, &tokenHandle) |> Bool.toOption(tokenHandle)

            trace "Get Uac.ProcessElevation" {
                return 
                    if Environment.OSVersion.Version.Major < 6 then ProcessElevation.Unsupported
                    else
                        match getTokenHandle () with
                        | None -> ProcessElevation.Unsupported
                        | Some handle -> 
                            use safeHandle = handle
                            use tokenElevationTypeBuffer = Marshal.allocGlobal2<int>

                            let mutable returnLength = 0
                            let success = NativeMethods.GetTokenInformation(safeHandle, TokenInformationType.TokenElevationType, tokenElevationTypeBuffer.Handle, tokenElevationTypeBuffer.Size, &returnLength)

                            match success, returnLength = tokenElevationTypeBuffer.Size with
                            | true,true -> enum(Marshal.ReadInt32(tokenElevationTypeBuffer.Handle))
                            | _ -> ProcessElevation.Default }

